package org.nf.web.servlet.mapping;

import cn.hutool.cache.impl.LFUCache;
import cn.hutool.core.text.AntPathMatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.nf.web.servlet.FrameworkContext;
import org.nf.web.servlet.HandlerExecutionChain;
import org.nf.web.servlet.HandlerInterceptorRegistration;
import org.nf.web.servlet.HandlerMapping;
import org.nf.web.servlet.annotation.Interceptor;

import java.util.Comparator;

/**
 * @author wangl
 * @date 2024/5/23
 */
public abstract class AbstractHandlerMapping implements HandlerMapping {

    /**
     * Ant路径匹配器
     */
    protected final AntPathMatcher pathMatcher = new AntPathMatcher();
    /**
     * LFU缓存
     * key保存请求的url
     * value保存映射的Ant路径
     */
    protected final LFUCache<String, String> lfuCache = new LFUCache<>(200);

    /**
     * 构建HandlerExecutionChain
     */
    protected HandlerExecutionChain getHandlerExecutionChain(HttpServletRequest request, Object handler) {
        if(handler != null) {
            HandlerExecutionChain chain = new HandlerExecutionChain(handler);
            HandlerInterceptorRegistration registration = FrameworkContext.getInstance().getInterceptorRegistration();
            registration.getInterceptors().forEach(interceptor -> {
                Interceptor annotation = interceptor.getClass().getAnnotation(Interceptor.class);
                String[] paths = annotation.value();
                String[] excludePaths = annotation.exclude();
                if(!antPath(excludePaths, request) && antPath(paths, request)) {
                    chain.addInterceptor(interceptor);
                }
            });
            //chain排序
            sort(chain);
            return chain;
        }
        return null;
    }

    /**
     * 拦截器排序
     */
    private void sort(HandlerExecutionChain chain) {
        chain.getInterceptorList().sort(
                Comparator.comparingInt(h -> h.getClass().getAnnotation(Interceptor.class).order()));
    }

    /**
     * 路径匹配
     */
    private boolean antPath(String[] paths, HttpServletRequest request) {
        for(String path : paths) {
            if(pathMatcher.match(path, getRequestURI(request))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取请求路径
     */
    protected String getRequestURI(HttpServletRequest request) {
        //查找映射前去掉uri的contextPath名称
        return request.getRequestURI().replace(request.getContextPath(), "");
    }
}